using System;
using System.Collections.Generic;
using System.Threading;

namespace muduoDotNet
{
    /// <summary>
    /// 性能计数器
    /// 用于收集和报告网络库的性能指标
    /// </summary>
    public static class PerformanceCounters
    {
        // 连接相关计数器
        private static long _activeConnections;
        private static long _totalConnections;
        private static long _failedConnections;
        
        // 数据传输相关计数器
        private static long _bytesSent;
        private static long _bytesReceived;
        private static long _messagesSent;
        private static long _messagesReceived;
        
        // 事件循环相关计数器
        private static long _eventLoopIterations;
        private static long _tasksExecuted;
        private static long _timersExecuted;
        
        // 错误相关计数器
        private static long _totalExceptions;
        private static long _networkExceptions;
        private static long _protocolExceptions;
        
        // 性能计时器
        private static long _totalProcessingTimeMs;
        private static long _maxProcessingTimeMs;
        private static long _minProcessingTimeMs = long.MaxValue;
        
        // 连接统计
        private static readonly Dictionary<string, ConnectionStats> _connectionStats = new Dictionary<string, ConnectionStats>();
        private static readonly object _statsLock = new object();

        /// <summary>
        /// 连接统计信息
        /// </summary>
        public class ConnectionStats
        {
            public string ConnectionName { get; set; }
            public long BytesSent { get; set; }
            public long BytesReceived { get; set; }
            public long MessagesSent { get; set; }
            public long MessagesReceived { get; set; }
            public long Exceptions { get; set; }
            public DateTime LastActivityTime { get; set; }
            public TimeSpan ConnectionDuration { get; set; }
        }

        #region 连接相关计数器

        public static long ActiveConnections => Interlocked.Read(ref _activeConnections);
        public static long TotalConnections => Interlocked.Read(ref _totalConnections);
        public static long FailedConnections => Interlocked.Read(ref _failedConnections);

        public static void IncrementActiveConnections()
        {
            Interlocked.Increment(ref _activeConnections);
            Interlocked.Increment(ref _totalConnections);
        }

        public static void IncrementTotalConnections()
        {
            Interlocked.Increment(ref _totalConnections);
        }

        public static void DecrementActiveConnections()
        {
            Interlocked.Decrement(ref _activeConnections);
        }

        public static void IncrementFailedConnections()
        {
            Interlocked.Increment(ref _failedConnections);
        }

        #endregion

        #region 数据传输相关计数器

        public static long BytesSent => Interlocked.Read(ref _bytesSent);
        public static long BytesReceived => Interlocked.Read(ref _bytesReceived);
        public static long MessagesSent => Interlocked.Read(ref _messagesSent);
        public static long MessagesReceived => Interlocked.Read(ref _messagesReceived);

        public static void AddBytesSent(long bytes)
        {
            Interlocked.Add(ref _bytesSent, bytes);
            Interlocked.Increment(ref _messagesSent);
        }

        public static void AddBytesReceived(long bytes)
        {
            Interlocked.Add(ref _bytesReceived, bytes);
            Interlocked.Increment(ref _messagesReceived);
        }

        #endregion

        #region 事件循环相关计数器

        public static long EventLoopIterations => Interlocked.Read(ref _eventLoopIterations);
        public static long TasksExecuted => Interlocked.Read(ref _tasksExecuted);
        public static long TimersExecuted => Interlocked.Read(ref _timersExecuted);

        public static void IncrementEventLoopIterations()
        {
            Interlocked.Increment(ref _eventLoopIterations);
        }

        public static void IncrementTasksExecuted()
        {
            Interlocked.Increment(ref _tasksExecuted);
        }

        public static void IncrementTimersExecuted()
        {
            Interlocked.Increment(ref _timersExecuted);
        }

        #endregion

        #region 错误相关计数器

        public static long TotalExceptions => Interlocked.Read(ref _totalExceptions);
        public static long NetworkExceptions => Interlocked.Read(ref _networkExceptions);
        public static long ProtocolExceptions => Interlocked.Read(ref _protocolExceptions);

        public static void IncrementTotalExceptions()
        {
            Interlocked.Increment(ref _totalExceptions);
        }

        public static void IncrementNetworkExceptions()
        {
            Interlocked.Increment(ref _networkExceptions);
            Interlocked.Increment(ref _totalExceptions);
        }

        public static void IncrementProtocolExceptions()
        {
            Interlocked.Increment(ref _protocolExceptions);
            Interlocked.Increment(ref _totalExceptions);
        }

        #endregion

        #region 性能计时器

        public static long TotalProcessingTimeMs => Interlocked.Read(ref _totalProcessingTimeMs);
        public static long MaxProcessingTimeMs => Interlocked.Read(ref _maxProcessingTimeMs);
        public static long MinProcessingTimeMs => Interlocked.Read(ref _minProcessingTimeMs);

        public static void RecordProcessingTime(long milliseconds)
        {
            Interlocked.Add(ref _totalProcessingTimeMs, milliseconds);
            
            // 更新最大处理时间
            long currentMax, newMax;
            do
            {
                currentMax = Interlocked.Read(ref _maxProcessingTimeMs);
                newMax = Math.Max(currentMax, milliseconds);
            } while (Interlocked.CompareExchange(ref _maxProcessingTimeMs, newMax, currentMax) != currentMax);
            
            // 更新最小处理时间
            long currentMin, newMin;
            do
            {
                currentMin = Interlocked.Read(ref _minProcessingTimeMs);
                newMin = Math.Min(currentMin, milliseconds);
            } while (Interlocked.CompareExchange(ref _minProcessingTimeMs, newMin, currentMin) != currentMin);
        }

        #endregion

        #region 连接统计管理

        public static void UpdateConnectionStats(string connectionName, long bytesSent, long bytesReceived, bool isError = false)
        {
            lock (_statsLock)
            {
                if (!_connectionStats.TryGetValue(connectionName, out var stats))
                {
                    stats = new ConnectionStats
                    {
                        ConnectionName = connectionName,
                        LastActivityTime = DateTime.UtcNow
                    };
                    _connectionStats[connectionName] = stats;
                }

                stats.BytesSent += bytesSent;
                stats.BytesReceived += bytesReceived;
                stats.LastActivityTime = DateTime.UtcNow;

                if (isError)
                {
                    stats.Exceptions++;
                }
            }
        }

        public static void RemoveConnectionStats(string connectionName)
        {
            lock (_statsLock)
            {
                _connectionStats.Remove(connectionName);
            }
        }

        public static Dictionary<string, ConnectionStats> GetConnectionStats()
        {
            lock (_statsLock)
            {
                return new Dictionary<string, ConnectionStats>(_connectionStats);
            }
        }

        #endregion

        #region 报告和重置

        /// <summary>
        /// 获取性能报告
        /// </summary>
        /// <returns>性能报告字符串</returns>
        public static string GetPerformanceReport()
        {
            var avgProcessingTime = EventLoopIterations > 0 ? TotalProcessingTimeMs / EventLoopIterations : 0;
            
            return $"Performance Report:\n" +
                   $"  Active Connections: {ActiveConnections}\n" +
                   $"  Total Connections: {TotalConnections}\n" +
                   $"  Failed Connections: {FailedConnections}\n" +
                   $"  Bytes Sent: {BytesSent:N0}\n" +
                   $"  Bytes Received: {BytesReceived:N0}\n" +
                   $"  Messages Sent: {MessagesSent:N0}\n" +
                   $"  Messages Received: {MessagesReceived:N0}\n" +
                   $"  Event Loop Iterations: {EventLoopIterations:N0}\n" +
                   $"  Tasks Executed: {TasksExecuted:N0}\n" +
                   $"  Timers Executed: {TimersExecuted:N0}\n" +
                   $"  Total Exceptions: {TotalExceptions:N0}\n" +
                   $"  Network Exceptions: {NetworkExceptions:N0}\n" +
                   $"  Protocol Exceptions: {ProtocolExceptions:N0}\n" +
                   $"  Total Processing Time: {TotalProcessingTimeMs:N0} ms\n" +
                   $"  Average Processing Time: {avgProcessingTime:N0} ms\n" +
                   $"  Max Processing Time: {MaxProcessingTimeMs:N0} ms\n" +
                   $"  Min Processing Time: {MinProcessingTimeMs:N0} ms";
        }

        /// <summary>
        /// 重置所有计数器
        /// </summary>
        public static void ResetCounters()
        {
            Interlocked.Exchange(ref _activeConnections, 0);
            Interlocked.Exchange(ref _totalConnections, 0);
            Interlocked.Exchange(ref _failedConnections, 0);
            Interlocked.Exchange(ref _bytesSent, 0);
            Interlocked.Exchange(ref _bytesReceived, 0);
            Interlocked.Exchange(ref _messagesSent, 0);
            Interlocked.Exchange(ref _messagesReceived, 0);
            Interlocked.Exchange(ref _eventLoopIterations, 0);
            Interlocked.Exchange(ref _tasksExecuted, 0);
            Interlocked.Exchange(ref _timersExecuted, 0);
            Interlocked.Exchange(ref _totalExceptions, 0);
            Interlocked.Exchange(ref _networkExceptions, 0);
            Interlocked.Exchange(ref _protocolExceptions, 0);
            Interlocked.Exchange(ref _totalProcessingTimeMs, 0);
            Interlocked.Exchange(ref _maxProcessingTimeMs, 0);
            Interlocked.Exchange(ref _minProcessingTimeMs, long.MaxValue);

            lock (_statsLock)
            {
                _connectionStats.Clear();
            }
        }

        #endregion
    }
}